package se.perp.c4.ui;

import java.awt.Point;
import java.awt.Polygon;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import se.perp.c4.model.Actor;
import se.perp.c4.model.Actor.Side;
import se.perp.c4.model.Territory;
import se.perp.c4.model.Territory.ETerritory;
import se.perp.c4.model.TerritoryCollection;

public class PieceOrderer {

    private static Side mySide = null;

    public static void setHomeSide(Side side) {
        mySide = side;
    }

    public static void orderAll(TerritoryCollection terrColl, PieceCollection pieceColl) {

        for (Territory t : terrColl) {
            PieceOrderer.orderIn(terrColl, pieceColl, t);
        }
    }

    private static Point polyCenter(Polygon p) {
        int xsum = 0, ysum = 0;
        for (int x : p.xpoints) {
            xsum += x;
        }
        for (int y : p.ypoints) {
            ysum += y;
        }
        return new Point(xsum / p.npoints, ysum / p.npoints);
    }

    public static void orderIn(
            TerritoryCollection coll,
            PieceCollection pieceColl,
            Territory t) {

        assert t != null;
        assert t.which != ETerritory.NOWHERE;

        final int GAP = 2;

        List<GamePiece> presentPieces = new LinkedList<GamePiece>();
        for (Actor a : t.getOccupants()) {
            presentPieces.add(pieceColl.get(a.who));
        }

        if (presentPieces.isEmpty()) {
            return;
        }

        Point center = polyCenter(RegionBounds.get(t.which));
        
        boolean isMyHome = (t.which == ETerritory.MORDOR && mySide == Side.DARK) ||
                (t.which == ETerritory.SHIRE && mySide == Side.LIGHT);
        boolean isOpponentHome =(t.which == ETerritory.MORDOR && mySide == Side.LIGHT) ||
                (t.which == ETerritory.SHIRE && mySide == Side.DARK);

        switch (presentPieces.size()) {
            case 1: {
                GamePiece a = presentPieces.get(0);
                a.setLocation(center.x - a.getWidth() / 2,
                        center.y - a.getHeight() / 2);
                a.remember();
                break;
            }
            case 2: {
                GamePiece aLeft = presentPieces.get(0);
                GamePiece aRight = presentPieces.get(1);
                aLeft.setLocation(center.x - aLeft.getWidth() - GAP,
                        center.y - aLeft.getHeight() / 2);
                aRight.setLocation(center.x + GAP,
                        center.y - aRight.getHeight() / 2);
                aLeft.remember();
                aRight.remember();
                break;

            }
            case 3: {
                GamePiece aSingle = presentPieces.get(0);
                GamePiece aLeft = presentPieces.get(1);
                GamePiece aRight = presentPieces.get(2);
                if (isOpponentHome) {
                    aSingle.setLocation(center.x - aSingle.getWidth() / 2,
                            center.y - aSingle.getHeight() - 2 * GAP);
                    aLeft.setLocation(center.x - aLeft.getWidth() - GAP,
                            center.y + GAP);
                    aRight.setLocation(center.x + GAP,
                            center.y + GAP);
                    aSingle.remember();
                    aLeft.remember();
                    aRight.remember();
                } else if (isMyHome) {
                    aSingle.setLocation(center.x - aSingle.getWidth() / 2,
                            center.y + GAP);
                    aLeft.setLocation(center.x - aLeft.getWidth() - GAP,
                            center.y - aLeft.getHeight());
                    aRight.setLocation(center.x + GAP,
                            center.y - aLeft.getHeight());
                    aSingle.remember();
                    aLeft.remember();
                    aRight.remember();
                } else {
                    Logger.getLogger(PieceOrderer.class.getName()).log(
                            Level.SEVERE, "Serious fuckup! 3 pieces in non-home territory!");
                }
                break;
            }

            case 4: {
                GamePiece[] as = new GamePiece[4];
                for (int i = 0; i <
                        4; i++) {
                    as[i] = presentPieces.get(i);
                }

                if (isOpponentHome) {
                    as[0].setLocation(center.x - as[0].getWidth() / 2,
                            center.y - as[0].getHeight() - 2 * GAP);
                    as[1].setLocation(center.x - (int) (1.5 * as[1].getWidth()) - GAP,
                            center.y + GAP);
                    as[2].setLocation(center.x - as[2].getWidth() / 2,
                            center.y + GAP);
                    as[3].setLocation(center.x + (int) as[2].getWidth() / 2 + GAP,
                            center.y + GAP);
                    for (int i = 0; i < 4; ++i) {
                        as[i].remember();
                    }
                } else if (isMyHome) {
                    as[0].setLocation(center.x - as[0].getWidth() / 2,
                            center.y + 2 * GAP);
                    as[1].setLocation(center.x - (int) (1.5 * as[2].getWidth()) - GAP,
                            center.y - as[1].getHeight() - GAP);
                    as[2].setLocation(center.x - as[2].getWidth() / 2,
                            center.y - as[2].getHeight() - GAP);
                    as[3].setLocation(center.x + as[2].getWidth() / 2 + GAP,
                            center.y - as[3].getHeight() - GAP);
                    for (int i = 0; i < 4; ++i) {
                        as[i].remember();
                    }
                } else {
                    Logger.getLogger(PieceOrderer.class.getName()).log(
                            Level.SEVERE, "Serious fuckup! 4 pieces in non-home territory!");
                }

                break;
            }

            default:
                Logger.getLogger(PieceOrderer.class.getName()).log(
                        Level.SEVERE, "Serious fuckup! Wrong number of actors! " + presentPieces.size());
        }

        if (mySide != Actor.sideFor(presentPieces.get(0).getActor()) &&
                presentPieces.size() > 1) {
            shufflePiecesIn(pieceColl, t);
        }
    }

    private static void shufflePiecesIn(PieceCollection pc, Territory t) {

        final int N = t.getOccupantCount();
        final List<Actor> occupants = t.getOccupants();
        Point[] locs = new Point[N];
        for (int i = 0; i < N; i++) {
            GamePiece gp = pc.get(occupants.get(i).who);
            locs[i] = gp.getLocation();
        }

        for (int i = 0; i < N; i++) {
            int j = (int) (Math.random() * N);
            Point p = locs[i];
            locs[i] = locs[j];
            locs[j] = p;
        }

        for (int i = 0; i < N; i++) {
            GamePiece gp = pc.get(occupants.get(i).who);
            gp.setLocation(locs[i]);
            gp.remember();
        }


    }
}
